package com.example.authorization.controller;

import cn.hutool.core.codec.Base64Decoder;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.example.authorization.api.ApiResult;
import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Strings;
import org.springframework.core.env.Environment;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/admin/api/v1/acl/user")
public class UserController {

    private Environment environment;
    private RegisteredClientRepository registeredClientRepository;
    private PasswordEncoder passwordEncoder;

    @GetMapping("/whoami")
    public ApiResult<Map<String, Object>> whoAmI() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        JwtAuthenticationToken token = (JwtAuthenticationToken) authentication;
        Jwt principal = (Jwt) token.getPrincipal();
        Map<String, Object> claims = principal.getClaims();
        return ApiResult.ok(claims);
    }

    @GetMapping("/test")
    public ApiResult<String> test() {
        return ApiResult.ok("test");
    }

    @PostMapping("/anon/login")
    public ApiResult<Object> login(@RequestBody AdminLoginDTO loginRequest) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        String authorization = request.getHeader("Authorization");
        if (Strings.isNullOrEmpty(authorization)) {
            throw new RuntimeException("Basic Auth请求头不能为空");
        }
        //解析 Authorization Basic Auth 请求头
        String clientInfo = new String(Base64Decoder.decode(authorization.replace("Basic ", "")));
        log.info("用户登录解析 Authorization Basic Auth 的客户端信息为:{}", clientInfo);
        //判断是否是正确的client
        String clientId = clientInfo.split(":")[0], clientSecret = clientInfo.split(":")[1];
        RegisteredClient client = registeredClientRepository.findByClientId(clientId);
        if (Objects.isNull(client)) {
            throw new RuntimeException("客户端信息未在授权服务器注册");
        }
        if (!passwordEncoder.matches(clientSecret, client.getClientSecret())) {
            throw new RuntimeException("客户端凭证不匹配");
        }

        HashMap<String, Object> objectHashMap = new HashMap<>();
        objectHashMap.put("grant_type", AuthorizationGrantType.PASSWORD.getValue());
        objectHashMap.put("username", loginRequest.getUsername());
        objectHashMap.put("password", loginRequest.getPassword());
        objectHashMap.put("scope", "all");
        String body = HttpRequest.post("http://localhost:" + environment.getProperty("local.server.port") + "/oauth2/token")
                .basicAuth(clientId, clientSecret)
                .form(objectHashMap)
                .execute().body();
        return ApiResult.ok(JSONUtil.toBean(body, Map.class));
    }


    @Data
    public static class AdminLoginDTO implements Serializable {
        private String username;

        private String password;
    }
}
